#pragma once
#include "Abstract.hpp"
#include "Detail.hpp"
#include "Fileds.hpp"
#include "Log.hpp"

namespace zgwrpc
{
    class JsonMessage : public BaseMessage // 继承Base
    {
    public:
        using ptr = std::shared_ptr<JsonMessage>;
        virtual std::string serialize() override
        {
            std::string ret;
            Serialize(_value, ret);
            return ret;
        }
        virtual bool unSerialize( std::string &data) override
        {
            return Deserialize(data, _value);
        }

    protected:
        Json::Value _value;
    };

    class JsonRequest : public JsonMessage // 根据具体的业务需求，继承不同的消息类
    {
    public:
        using ptr = shared_ptr<JsonRequest>;
    };

    class JsonResponse : public JsonMessage // 根据具体的业务需求，继承不同的消息类
    {
    public:
        using ptr = shared_ptr<JsonResponse>;
        virtual bool check() override
        {
            if (_value[KEY_RCODE].isNull() == true)
            {
                LOG(LogLevel::DEBUG) << "响应中没有响应状态码";
                return false;
            }
            if (_value[KEY_RCODE].isIntegral() == false)
            {
                LOG(LogLevel::DEBUG) << "响应状态码不是整形";
                return false;
            }
            return true;
        }
        RCode rCode()
        {
            return (RCode)_value[KEY_RCODE].asInt();
        }
        void setRCode(RCode rcode)
        {
            _value[KEY_RCODE] = (int)rcode;
        }
    };
    class RpcRequest : public JsonRequest // 根据需求定制RPC请求  rpc请求不需要设置RPCOPType,因为它是由客户端发起的
    {
    public:
        using ptr = shared_ptr<RpcRequest>;
        virtual bool check() override
        {
            if (_value[KEY_METHOD].isNull() == true || _value[KEY_METHOD].isString() == false) // 判断RPC请求是否有方法名称
            {
                LOG(LogLevel::DEBUG) << "rpc请求中没有方法名或方法名称错误";
                return false;
            }
            if (_value[KEY_PARAMS].isNull() == true || _value[KEY_PARAMS].isObject() == false) // 判断RPC请求是否有参数
            {
                LOG(LogLevel::DEBUG) << "rpc请求中没有参数或参数格式错误";
                return false;
            }
            if (_value[KEY_OPTYPE].isNull() == true || _value[KEY_OPTYPE].isIntegral() == false)
            {
                LOG(LogLevel::DEBUG) << "rpc请求中没有操作类型或操作类型格式错误";
                return false;
            }
            return true;
        }
        std::string method() // 获取RPC请求的方法名称
        {
            return _value[KEY_METHOD].asString();
        }

        virtual void setMethod(const std::string &method) // 设置RPC请求的方法名称
        {
            _value[KEY_METHOD] = method;
        }

        Json::Value params() // 获取RPC请求的参数
        {
            return _value[KEY_PARAMS];
        }

        void setParams(const Json::Value &params) // 设置RPC请求的参数
        {
            _value[KEY_PARAMS] = params;
        }

        void setOpType(Rtype op_type)
        {
            _value[KEY_OPTYPE] = (int)op_type;
        }
        Rtype opType()
        {
            return (Rtype)_value[KEY_OPTYPE].asInt();
        }
        void setRtype(Rtype rtype)
        {
            _value[KEY_OPTYPE] = (int)rtype;
        }
    };

    class TopicRequest : public JsonRequest // 根据需求定制Topic请求
    {
    public:
        using ptr = shared_ptr<TopicRequest>;
        virtual bool check() override // 检查Topic请求是否合法
        {
            if (_value[KEY_TOPIC_KEY].isNull() == true || _value[KEY_TOPIC_KEY].isString() == false) // 判断RPC请求是否有方法名称
            {
                LOG(LogLevel::DEBUG) << "主题请求中没有主题关键字或主题关键字错误";
                return false;
            }
            if(_value[KEY_TOPIC_MSG].isNull()==true || _value[KEY_TOPIC_MSG].isString()==false)
            {
                LOG(LogLevel::DEBUG) << "主题请求中没有主题消息或主题消息错误";
            }
            if (_value[KEY_OPTYPE].asInt() == (int)TopicOpType::TOPIC_PUBLISH &&
                (_value[KEY_TOPIC_MSG].isNull() == true || _value[KEY_TOPIC_MSG].isString() == false))
            {
                LOG(LogLevel::DEBUG) << "发布主题请求中没有主题消息或主题消息错误";
                return false;
            }
            return true;
        }
        void setTopicKey(const std::string &topic_key) // 设置主题关键字
        {
            _value[KEY_TOPIC_KEY] = topic_key;
        }

        std::string topicKey() // 获取主题关键字
        {
            return _value[KEY_TOPIC_KEY].asString();
        }

        TopicOpType topicOpType()
        {
            return (TopicOpType)_value[KEY_OPTYPE].asInt();
        }
        void setTopicOpType(TopicOpType op_type) // 设置主题操作类型
        {
            _value[KEY_OPTYPE] = (int)op_type;
        }
        std::string topicMsg() // 获取主题消息
        {
            return _value[KEY_TOPIC_MSG].asString();
        }
        void setTopicMsg(const std::string &msg)
        {
            _value[KEY_TOPIC_MSG] = msg;
        }
    };

    typedef std::pair<std::string, int> Address; // 定义主机地址类型
    class ServiceRequest : public JsonRequest    // 定制Service请求
    {
    public:
        using ptr = shared_ptr<ServiceRequest>;
        virtual bool check() override // 检查Topic请求是否合法
        {
            if (_value[KEY_METHOD].isNull() == true || _value[KEY_METHOD].isString() == false) // 判断RPC请求是否有方法名称
            {
                LOG(LogLevel::DEBUG) << "服务请求中没有方法名或方法名称错误";
                return false;
            }
            //如果请求方法是一个服务发现请求， 就不需要检查主机信息，因为原本的服务器中就没有注册这个服务
            if (_value[KEY_OPTYPE].asInt() != (int)ServiceOpType::SERVICE_DISCOVERY &&
                (_value[KEY_HOST].isNull() == true || _value[KEY_HOST].isObject() == false ||
                 _value[KEY_HOST][KEY_HOST_IP].isNull() == true || _value[KEY_HOST][KEY_HOST_IP].isString() == false ||
                 _value[KEY_HOST][KEY_HOST_PORT].isNull() == true || _value[KEY_HOST][KEY_HOST_PORT].isIntegral() == false))
            {
                LOG(LogLevel::DEBUG) << "服务请求中没有主机信息或主机信息格式错误";
                return false;
            }
            return true;
        }
        std::string method() // 获取服务请求的方法名称
        {
            return _value[KEY_METHOD].asString();
        }
        void setMethod(const std::string &method) // 设置服务请求的方法名称
        {
            _value[KEY_METHOD] = method;
        }

        void setServiceOpType(ServiceOpType op_type)
        {
            _value[KEY_OPTYPE] = (int)op_type;
        }
        ServiceOpType serviceOpType()
        {
            return (ServiceOpType)_value[KEY_OPTYPE].asInt();
        }
        Address host()
        {
            Address addr;
            addr.first = _value[KEY_HOST][KEY_HOST_IP].asString();
            addr.second = _value[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }
        void setHost(const Address &host)
        {
            Json::Value val;
            val[KEY_HOST_IP] = host.first;
            val[KEY_HOST_PORT] = host.second;
            _value[KEY_HOST] = val;
        }
    };

    // 响应类

    class RpcResponse : public JsonResponse
    {
    public:
        using ptr = shared_ptr<RpcResponse>;
        virtual bool check() override
        {
            if (_value[KEY_RCODE].isNull() == true)
            {
                LOG(LogLevel::DEBUG) << "响应中没有响应状态码";
                return false;
            }
            if (_value[KEY_RCODE].isIntegral() == false)
            {
                LOG(LogLevel::DEBUG) << "响应状态码不是整形";
                return false;
            }
            if (_value[KEY_RESULT].isNull() == true || _value[KEY_RESULT].isObject() == false) // 返回值一定是个object
            {
                LOG(LogLevel::DEBUG) << "响应中没有响应结果或响应结果格式错误";
                return false;
            }
            return true;
        }

        Json::Value result()
        {
            return _value[KEY_RESULT];
        }
        void setResult(const Json::Value &result)
        {
            _value[KEY_RESULT] = result;
        }
    };
    class TopicResponse : public JsonResponse
    {
        public:
        using ptr = shared_ptr<TopicResponse>;
    };

    class ServiceResponse : public JsonResponse
    {
    public:
        using ptr = shared_ptr<ServiceResponse>;
        virtual bool check() override
        {
            if (_value[KEY_RCODE].isNull() == true || _value[KEY_RCODE].isIntegral() == false)
            {
                LOG(LogLevel::DEBUG) << "响应中没有响应状态码或响应状态码格式错误";
                return false;
            }
            if (_value[KEY_OPTYPE].asInt() == (int)ServiceOpType::SERVICE_DISCOVERY && (_value[KEY_METHOD].isNull() == true || _value[KEY_METHOD].isString() == false ||
                                                                                        _value[KEY_HOST].isNull() == true || _value[KEY_HOST].isArray() == false))
            {
                LOG(LogLevel::DEBUG) << "发现服务响应中没有方法名或方法名格式错误或没有主机信息或主机信息格式错误";
                return false;
            }
            return true;
        }

        std::string method()
        {
            return _value[KEY_METHOD].asString();
        }
        void setMethod(const std::string &method)
        {
            _value[KEY_METHOD] = method;
        }

        void setHost(std::vector<Address> hosts)
        {
            for (auto &host : hosts)
            {
                Json::Value val;
                val[KEY_HOST_IP] = host.first;
                val[KEY_HOST_PORT] = host.second;
                _value[KEY_HOST].append(val);
            }
        }
        std::vector<Address> hosts()
        {
            std::vector<Address> hosts;
            int sz = _value[KEY_HOST].size();
            for (int i = 0; i < sz; i++)
            {
                Address addr;
                addr.first = _value[KEY_HOST][i][KEY_HOST_IP].asString();
                addr.second = _value[KEY_HOST][i][KEY_HOST_PORT].asInt();
                hosts.push_back(addr);
            }
            return hosts;
        }
        void setServiceOpType(ServiceOpType op_type)
        {
            _value[KEY_OPTYPE] = (int)op_type;
        }
        ServiceOpType serviceOpType()
        {
            return (ServiceOpType)_value[KEY_OPTYPE].asInt();
        }
    };


    class MessageFactory
    {
    public:
        static BaseMessage::ptr createMessage(MType mtype)
        {
            switch (mtype)
            {
            case MType::REQ_RPC:
                return std::make_shared<zgwrpc::RpcRequest>();
            case MType::RSP_RPC:
                return std::make_shared<RpcResponse>();
            case MType::REQ_TOPIC:
                return std::make_shared<TopicRequest>();
            case MType::RSP_TOPIC:
                return std::make_shared<TopicResponse>();
            case MType::REQ_SERVICE:
                return std::make_shared<ServiceRequest>();
            case MType::RSP_SERVICE:
                return std::make_shared<ServiceResponse>();
                default:
                return  BaseMessage::ptr();
            }
        }
        template<typename T, typename ...Args>
        static shared_ptr<T> create(Args&&... args)
        {
            return std::make_shared<T>(std::forward<Args>(args)...);
        }
    };
}
